package file;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Base64;
import java.util.Scanner;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.junit.Test;

public class RandomAccessFileTest2 {
	
	public static final Encoder encoder = Base64.getEncoder();
	public static final Decoder decoder = Base64.getDecoder();
	
	@Test
	public void write() throws IOException{
		
		RandomAccessFile file = new RandomAccessFile("b.txt", "rw");
		file.writeLong(8l);
		file.writeUTF("\r\n");
		
		String data = "撒打发斯蒂芬\r\n十分        大师傅的三大";
		file.writeUTF(URLEncoder.encode(data, "utf-8"));
		file.writeUTF("\r\n");
		
		data = "啊撒打发斯蒂芬\r\n啊啥        地方撒旦";
		file.writeUTF(URLEncoder.encode(data, "utf-8"));
		file.writeUTF("\r\n");
		file.close();
	}
	
	//并发写测试，要保证都是在最后追加
	@Test
	public void writeConrrent() throws IOException, InterruptedException{
		
		int count = 4;
		ExecutorService service = Executors.newFixedThreadPool(count);
		CountDownLatch countDown = new CountDownLatch(count);
		for(int i = 0; i < count; i++){
			service.execute(()->{
				try {
					RandomAccessFile file = new RandomAccessFile("b.txt", "rw");
					FileChannel channel = file.getChannel();
					for(int j = 0; j < 100; j++){
						FileLock lock = channel.lock();
						try{
							file.seek(file.length());
							file.writeUTF(String.valueOf(j));
							file.writeUTF("\r\n");
						} finally {
							lock.release();
						}
					}
					countDown.countDown();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			});
		}
		countDown.await();
	}
	
	//并发写测试，要保证都是在最后追加
	@Test
	public void writeConrrent2() throws IOException, InterruptedException{
		
		int count = 4;
		ExecutorService service = Executors.newFixedThreadPool(count);
		CountDownLatch countDown = new CountDownLatch(count);
		for(int i = 0; i < count; i++){
			service.execute(()->{
				System.out.println(Thread.currentThread().getName() + "进入");
				try(PrintWriter file = new PrintWriter(new FileOutputStream("c.txt", true))){  //保证了是追加，不会出现覆盖的情况
					System.out.println(Thread.currentThread().getName() + "开始写");
					file.println(0); //设置头
					for(int j = 0; j < 100; j++){
						file.println(Thread.currentThread().getName() + ":" + String.valueOf(j));
					}
					countDown.countDown();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}
			});
		}
		countDown.await();
	}
	
	//并发读测试
	@Test
	public void readConrrent() throws IOException, InterruptedException{
		
		int count = 4;
		ExecutorService service = Executors.newFixedThreadPool(count);
		CountDownLatch countDown = new CountDownLatch(count);
		for(int i = 0; i < count; i++){
			service.execute(()->{
				try(
						RandomAccessFile file = new RandomAccessFile("c.txt", "rw");
						FileChannel channel = file.getChannel();
						){
					
					countDown.countDown();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			});
		}
		countDown.await();
	}

	@Test
	public void read() throws IOException {
		
		RandomAccessFile file = new RandomAccessFile("b.txt", "r");
		file.seek(8);
		file.readUTF();
		while(file.getFilePointer() < file.length()){
			System.out.println(URLDecoder.decode(file.readUTF(), "utf-8"));
			file.readUTF();
		}
		file.close();
	}
	
	@Test
	public void base64(){
		String data = "啊撒打发斯蒂芬\r\n=12324#$%$^%$&$%<>?:";
		String encode = encoder.encodeToString(data.getBytes());
		System.out.println(encode);
		
		String decode = new String(decoder.decode(encode));
		System.out.println(decode);
	}
}
